package com.sky.aspect;

import com.sky.annotation.AutoFill;
import com.sky.annotation.RefreshRedis;
import com.sky.constant.RedisMethodType;
import com.sky.enumeration.OperationType;
import com.sky.result.Result;
import com.sky.vo.DishVO;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.DependsOn;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;

import java.util.List;
import java.util.Set;

/*
* 刷新Redis缓存切面
* 仅支持删除缓存*/
@Aspect
@Component
@Slf4j
public class RefreshRedisAspect {

    @Autowired
    private RedisTemplate redisTemplate;
    /*
     * 切入点
     * */
    @Pointcut("execution(* com.sky.controller.*.*.*(..)) && @annotation(com.sky.annotation.RefreshRedis)")
    public void Pointcut() {}

    //环绕通知
    @Around("Pointcut()")
    public Object around(ProceedingJoinPoint joinPoint) throws Throwable {
        //获取注解上的参数值,即拼接的前置key参数如：dish_
        MethodSignature signature = (MethodSignature) joinPoint.getSignature();
        RefreshRedis annotation = signature.getMethod().getAnnotation(RefreshRedis.class);
        String pre_key = annotation.key();
        RedisMethodType method_type = annotation.method_type();

        //获取方法参数
        Object[] args = joinPoint.getArgs();
        String id = "";
        if (args.length == 1) {id = String.valueOf(args[0]) ;}
        String key = pre_key + id;

        //根据方法名判断操作
        if(method_type == RedisMethodType.DELETE) {
            //执行原方法
            Object result = joinPoint.proceed();
            //删除缓存
            redisDelete(pre_key);
            //返回结果
            return result;
        }else if(method_type == RedisMethodType.SELECT){

            //查询缓存，并设置缓存

            Object cacheResult  = redisTemplate.opsForValue().get(key);

            //判断缓存中是否与原方法返回类型一致
            if (cacheResult != null && isValidDishVOList(cacheResult)) {
                log.info("查询缓存成功，key为：" + key);
                return Result.success((List<DishVO>) cacheResult);
            }else{
                // 如缓存中无数据，或者与需要的类型不匹配，执行原方法并更新缓存
                log.info("缓存未命中或类型不匹配，执行原方法...");
                Object result = joinPoint.proceed();

                // 将原方法结果存入缓存（需确保是List<DishVO>）
                // 判断是否为Result类型->判断是否为成功、是否为list类型->判断是否为DishVO类型
                if (result instanceof Result<?> ResultVo) {
                    if (ResultVo.getCode()==1 && ResultVo.getData() instanceof List<?> dishVOList) {
                        if (isValidDishVOList(dishVOList)){
                            redisTemplate.opsForValue().set(key, dishVOList);
                            log.info("更新缓存成功，key为：{}", key);
                        }
                    }
                }
                return result;
            }

        }else {
            //直接执行原方法
            return joinPoint.proceed();
        }

    }

    //删除缓存
    private void redisDelete(String preKey) {
        Set keys = redisTemplate.keys(preKey + "*");
        if (keys != null && !keys.isEmpty()) {
            redisTemplate.delete(keys);
            log.info("删除缓存成功，key为：" + preKey + "*");
        }
    }

    /**
     * 验证缓存结果是否为List<DishVO>
     *   为DishVO实例的List，返回true，否则返回false
     */
    private boolean isValidDishVOList(Object cacheResult) {
        if (!(cacheResult instanceof List<?> list)) {
            return false;
        }
        // 空列表无法验证元素类型，默认认为合法（根据业务需求调整）
        if (list.isEmpty()) {
            return true;
        }

//        原式：
//        for (Object element : list) {
//            if (!(element instanceof DishVO)) {
//                return false; // 发现非法元素立即终止
//            }
//        }
        // 检查列表中所有元素是否为DishVO实例
        return list.stream().allMatch(element -> element instanceof DishVO);
    }



}
